package com.t2two.example.common.utils;

import org.bouncycastle.asn1.gm.GMNamedCurves;
import org.bouncycastle.asn1.x9.X9ECParameters;
import org.bouncycastle.crypto.engines.SM2Engine;
import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.crypto.params.ParametersWithRandom;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

import java.security.*;
import java.security.spec.ECGenParameterSpec;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;

/**
 * @version 1.0
 * @description: TODO
 * @author: lifei
 * @date: 2025/2/20 11:53
 */
public class SM2Utils {
    static {
        // 添加 Bouncy Castle 提供者
        Security.addProvider(new BouncyCastleProvider());
    }

    // 生成 SM2 密钥对
    public static KeyPair generateKeyPair() throws NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException {
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("SM2", "BC");
        ECGenParameterSpec sm2Spec = new ECGenParameterSpec("sm2p256v1");
        keyPairGenerator.initialize(sm2Spec, new SecureRandom());
        return keyPairGenerator.generateKeyPair();
    }

    // 公钥加密
    public static String encrypt(String plainText, String publicKeyBase64) throws Exception {
        PublicKey publicKey = getPublicKeyFromBase64(publicKeyBase64);
        X9ECParameters sm2ECParameters = GMNamedCurves.getByName("sm2p256v1");
        ECDomainParameters domainParameters = new ECDomainParameters(sm2ECParameters.getCurve(), sm2ECParameters.getG(), sm2ECParameters.getN());
        BCECPublicKey bcecPublicKey = (BCECPublicKey) publicKey;
        ECPublicKeyParameters publicKeyParameters = new ECPublicKeyParameters(bcecPublicKey.getQ(), domainParameters);

        SM2Engine sm2Engine = new SM2Engine();
        sm2Engine.init(true, new ParametersWithRandom(publicKeyParameters, new SecureRandom()));
        byte[] in = plainText.getBytes();
        byte[] out = sm2Engine.processBlock(in, 0, in.length);
        return Base64.getEncoder().encodeToString(out);
    }

    // 私钥解密
    public static String decrypt(String cipherText, String privateKeyBase64) throws Exception {
        PrivateKey privateKey = getPrivateKeyFromBase64(privateKeyBase64);
        X9ECParameters sm2ECParameters = GMNamedCurves.getByName("sm2p256v1");
        ECDomainParameters domainParameters = new ECDomainParameters(sm2ECParameters.getCurve(), sm2ECParameters.getG(), sm2ECParameters.getN());
        BCECPrivateKey bcecPrivateKey = (BCECPrivateKey) privateKey;
        ECPrivateKeyParameters privateKeyParameters = new ECPrivateKeyParameters(bcecPrivateKey.getD(), domainParameters);

        SM2Engine sm2Engine = new SM2Engine();
        sm2Engine.init(false, privateKeyParameters);
        byte[] in = Base64.getDecoder().decode(cipherText);
        byte[] out = sm2Engine.processBlock(in, 0, in.length);
        return new String(out);
    }

    // 将 Base64 编码的公钥字符串转换为 PublicKey 对象
    public static PublicKey getPublicKeyFromBase64(String publicKeyBase64) throws Exception {
        byte[] publicKeyBytes = Base64.getDecoder().decode(publicKeyBase64);
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKeyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("SM2", "BC");
        return keyFactory.generatePublic(keySpec);
    }

    // 将 Base64 编码的私钥字符串转换为 PrivateKey 对象
    public static PrivateKey getPrivateKeyFromBase64(String privateKeyBase64) throws Exception {
        byte[] privateKeyBytes = Base64.getDecoder().decode(privateKeyBase64);
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("SM2", "BC");
        return keyFactory.generatePrivate(keySpec);
    }

    // 将公钥转换为 Base64 编码的字符串
    public static String getPublicKeyBase64(PublicKey publicKey) {
        return Base64.getEncoder().encodeToString(publicKey.getEncoded());
    }

    // 将私钥转换为 Base64 编码的字符串
    public static String getPrivateKeyBase64(PrivateKey privateKey) {
        return Base64.getEncoder().encodeToString(privateKey.getEncoded());
    }


    public static void main(String[] args) {
        String to = "04ac5724c05b8a145abbc7afdcc0766565971bb307d6da93ba4bd735fe1addfef3a58b37aa3238c52c1efdc1add84e3e63f06516967feca19496c24f643381c62a64722ff549485a72b1216b98db0521d807c29a14d663af76c92c30e06336d8f447e5b7ddf68a695ed38d6825e2d1face2101143c06cea26a56a77de3fe61373c67a4c72fc4fb53cf3881e9b6164dd966b30b9f1e6417caa906728d7ce26504066f3b279d442526a854f426bc06e4fda69a968ad69b59acc915092dacff62dd34b65111b8883f3d1e722aa063812f5830bc0df32587e458ea739a6cf0a24d4e90c3e045d49a3b103f586ae61d640b72f7e69169a9cf2a1499f2aa391a6fcd5c7755f1fef61346ced2087ab9a1527a85d93eefbc527d43c5f8ba648cb02220e188d31e4a7ed89bb4d94b3abe31c2a83985b4603374b39561cd96d944ea3d45c54f1cb03ea318365b05b70f83c461f0b55cf956b3121389874f66760761f0e2a4dc9ac89e79bf8fdcc6e2e4ecf39bf8a49fc40b6e0dea0e65900d0f4e9fa912c1c84e99133a77eaff3b5fdceb5e587fde3e3dc6c20cb3bc4a9223f4e4e2d904d546ee42c3cfabb9902d938ce2b6d0d5961ab119968e287d774a87f09cd7175bf2e93a5ee9bf002965c73ac31c79eee0f057c93bab2da5824adb065a8fa7205074d27b9d371248d7a89be51fea3c0f9eec92790c335e0185c18b2513c925f679f59443ffa3eeb8715e86cacdf451f2485041f6cbebaa0fa49e3ce8efcc9d771647a101f991dff77de1cedaf06f56c17dc02adb2974249a34a852920568d1d9455488f5a19b347d0700cc0f7313adb5b65a344fbc7066cd3809e44416fe60128389cb3194de5fcdf44bb6535b4761788e8bd9d9a62fbbcc0224e079d1b0b987cb7dbfc4a4ccf64f705ea872b70c958caf1c4bb5929a62a9747d105be91a43ef1341e571a2eb4cbdcba88f5fed7e4493f16b88bbae1739dec375f9e053d2ddfc2e53e8aca17d6ca68ac5106342b4098c7396adb45fcc9a7f3d3c8a40c183f31a6ad0c9774b3a5a285b65dc1d53a8df76ed0c9f7aba8a55e306adcf93666385498513546af9ad9da241bbb5d42ba813350c89e877614d435297a0f81322cd0c1d6a3a7e155d98a1fcc5466695aca14e2d0bd59008c6031719631e3a300daff7b80a6ba6f3dad08f81455ee72a0e60921e158bbec2e498ee80744483ef375862d69ec0a2983b14a59637f12cded8b6c942774e01f8c0855e98baadeae4db321e29d6e6f15b3c1d6b8d81d25fad988774";
//        decrypt(to,getPrivateKeyBase64())
    }
}
